#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <time.h>
#include <ctype.h>
#include <stddef.h>
#include "osa.h"
#include "UART.h"
#include "sockets.h"
#include "ip_addr.h"
#include "netdb.h"
#include "sys.h"
#include "sdk_api.h"
#include "guilin.h"

/*
	 _task3  可以不用看

	_task  读串口3数据

	_task2 负责升级

	xmodem_send1 升级boot

	xmodem_send2 升级 fw
*/

#define sleep(x) OSATaskSleep((x) * 200)//second

// debug uart log
#define sdk_uart_printf(fmt, args...) do { RTI_LOG("[sdk]"fmt, ##args); } while(0)
// CATStudio usb log
#define catstudio_printf(fmt, args...) do { CPUartLogPrintf("[sdk]"fmt, ##args); } while(0)

#define sleep(x) OSATaskSleep((x) * 200)//second

#define _TASK_STACK_SIZE     12800
static UINT32 _task_stack[_TASK_STACK_SIZE/sizeof(UINT32)];
static UINT32 _task_stack2[_TASK_STACK_SIZE/sizeof(UINT32)];
static UINT32 _task_stack3[_TASK_STACK_SIZE/sizeof(UINT32)];

static OSTaskRef _task_ref = NULL;
static OSTaskRef _task_ref2 = NULL;
static OSTaskRef _task_ref3 = NULL;
static OSATimerRef _timer_ref = NULL;
static OSFlagRef _flag_ref = NULL;

#define TASK_TIMER_CHANGE_FLAG_BIT    0x01

static void _timer_callback(UINT32 tmrId);
static void _task(void *ptr);
static void _task2(void *ptr);
static void _task3(void *ptr);

extern void update_the_cp_ver(char *cp_ver);	// max length 128
// Device bootup hook before Phase1Inits.
// If you have some work to be init, you may implete it here.
// ex: you may start your task here. or do some initialize here.
extern void Phase1Inits_enter(void);
// Device bootup hook after Phase1Inits.
// If you have some work to be init, you may implete it here.
// ex: you may start your task here. or do some initialize here.
extern void Phase1Inits_exit(void);
// Device bootup hook before Phase2Inits.
// If you have some work to be init, you may implete it here.
// ex: you may start your task here. or do some initialize here.
extern void Phase2Inits_enter(void);
// Device bootup hook after Phase2Inits.
// If you have some work to be init, you may implete it here.
// ex: you may start your task here. or do some initialize here.
extern void Phase2Inits_exit(void);


void Phase1Inits_enter(void)
{
}

void Phase1Inits_exit(void)
{
}

void Phase2Inits_enter(void)
{
}
#include "osa.h"
#include "UART.h"
#include "sdk_api.h"
#define GPS_MSGQ_MSG_SIZE (sizeof(msgGPSDataParam))
extern OSMsgQRef    GpsDataMsgQ;

#define GPS_MSGQ_QUEUE_SIZE            (8)
void Phase2Inits_exit(void)
{
    int ret;
	
    ret = OSAFlagCreate(&_flag_ref);
    ASSERT(ret == OS_SUCCESS);

    ret = OSATimerCreate(&_timer_ref);
    ASSERT(ret == OS_SUCCESS);

    ret = OSATaskCreate(&_task_ref, _task_stack, _TASK_STACK_SIZE, 120, "test-task", _task, NULL);
    ASSERT(ret == OS_SUCCESS);

    ret = OSATaskCreate(&_task_ref2, _task_stack2, _TASK_STACK_SIZE, 120, "test-task2", _task2, NULL);
    ASSERT(ret == OS_SUCCESS);

    ret = OSAMsgQCreate(&GpsDataMsgQ, "gpsDataMsgQ", GPS_MSGQ_MSG_SIZE, GPS_MSGQ_QUEUE_SIZE, OS_FIFO);
    ASSERT(ret == OS_SUCCESS);

    ret = OSATaskCreate(&_task_ref3, _task_stack3, _TASK_STACK_SIZE, 180, "gps-task", _task3, NULL);
    ASSERT(ret == OS_SUCCESS);

	sdk_uart_printf("Phase2Inits_exit OSATimerStart\n");

    OSATimerStart(_timer_ref, 10 * 200, 10 * 200, _timer_callback, 0); // 10 seconds timer
}

static void _timer_callback(UINT32 tmrId)
{
    OSAFlagSet(_flag_ref, TASK_TIMER_CHANGE_FLAG_BIT, OSA_FLAG_OR);
}

//unsigned char lkf[13072] = {};
#include "osa.h"
#include "UART.h"
#include "sdk_api.h"
#include "guilin.h"


#define XMODEM_SOH 0x01
#define XMODEM_STX 0x02
#define XMODEM_EOT 0x04
#define XMODEM_ACK 0x06
#define XMODEM_NAK 0x15
#define XMODEM_CAN 0x18
#define XMODEM_CRC_CHR	'C'
#define XMODEM_CRC_SIZE 2		/* Crc_High Byte + Crc_Low Byte */
#define XMODEM_FRAME_ID_SIZE 2 		/* Frame_Id + 255-Frame_Id */

#define XMODEM_DATA_SIZE_SOH 128  	/* for Xmodem protocol */
#define XMODEM_DATA_SIZE_STX 1024 	/* for 1K xmodem protocol */

#define XMODEM_HEAD		XMODEM_STX
#define XMODEM_DATA_SIZE 	XMODEM_DATA_SIZE_STX

int lkfm  = 0;
int lkfm2  = 0;
int lkfm3  = 0;
int lkfm4  = 0;
int ilkf = 0;

unsigned short get_crc16 ( char *ptr, unsigned short count )
{
	unsigned short crc, i;
	crc = 0;
	while(count--)
	{
		crc = crc ^ (int) *ptr++ << 8;

		for(i = 0; i < 8; i++)
		{
			if(crc & 0x8000)
				crc = crc << 1 ^ 0x1021;
			else
				crc = crc << 1;
		}
	}
	return (crc & 0xFFFF);
}

unsigned char ack_id = 'C';
int xmodem_send1()
{
    char packet_data[XMODEM_DATA_SIZE];
    char frame_data[XMODEM_DATA_SIZE + XMODEM_CRC_SIZE + XMODEM_FRAME_ID_SIZE + 1];

    unsigned short crc_value;
    int complete = 0;
    int retry_num = 0;
    int pack_counter = 0;
    int read_number = 0;
    ack_id = 'C';
    int fd = 0;
	int ac = 0;
//     int bootfl = 20180;
//     fd = FDI_fopen("boot_file", "rb");
    int bootfl = 13072;
	int bootfl_t;
	 int i = 0;

    //fd = FDI_fopen("boot_file1", "rb");
    if (fd) 
    {
        sdk_uart_printf("debug> open file for read OK\n");
    }
    else 
    {
        sdk_uart_printf("debug> open file for read error\n");
        return -1;
    }

    while(!complete)
	{
        switch(ack_id)
		{
            case XMODEM_CRC_CHR:	// 接收到字符'C'开始启动传输，并使用CRC校验
                sdk_uart_printf("begining to Send...\r\n");
            case XMODEM_ACK:        //0x06
                retry_num = 0;
				pack_counter++;

                if(bootfl <= 0)
                {
                    ack_id = XMODEM_EOT;
                    complete = 1;
                    //FDI_fclose(fd);
                    UART3_SEND_DATA(&ack_id, 1);

                    sdk_uart_printf("Send file successful!!!\n");
                    sleep(3);
                    break;
                }

				bootfl_t = bootfl;
                bootfl -= XMODEM_DATA_SIZE;
                if (bootfl >= 0)
                {
                    memset(packet_data, 0, XMODEM_DATA_SIZE);
                    //FDI_fread(packet_data, XMODEM_DATA_SIZE, 1, fd);

                }
                else
                {
                    memset(packet_data, 0, bootfl_t);
                    //FDI_fread(packet_data, bootfl_t, 1, fd);
                    read_number = bootfl_t;
                    for(; read_number < XMODEM_DATA_SIZE; read_number++)
                    {
						packet_data[read_number] = 0x1A;
                    }
                }

                frame_data[0] = XMODEM_HEAD;  // 帧开始字符
				frame_data[1] = (char)pack_counter;  // 信息包序号
				frame_data[2] = (char)(255 - frame_data[1]);  // 信息包序号的补码
               
                for(i = 0; i < XMODEM_DATA_SIZE; i++)  // 128字节的数据段
				    frame_data[i+3] = packet_data[i];//把收到的字符和信息头一起打包

				crc_value = get_crc16(packet_data,  XMODEM_DATA_SIZE); // 16位crc校验

				frame_data[XMODEM_DATA_SIZE + 3] = (unsigned char)(crc_value >> 8);// 高八位数据
				frame_data[XMODEM_DATA_SIZE + 4] = (unsigned char)(crc_value);     //低八位数据

                UART3_SEND_DATA((char *)frame_data, XMODEM_DATA_SIZE + 5);

                while(1)
                {
                    if(lkfm3 == 1 )
                    {
                        lkfm3 = 0;
                        //sdk_uart_printf("aaa4\n");
                        //ack_id = XMODEM_ACK;
                        break;
                    }
                    OSATaskSleep(1);
                }
                break;


            case XMODEM_NAK:
                sdk_uart_printf("XMODEM_NAK\n");
                break;


            default:
                complete = 1;
                return -1;
        }
    }
}

int xmodem_send2()
{
    sdk_uart_printf("xmodem_send2 --- \n");
    //sleep(10);
    char packet_data[XMODEM_DATA_SIZE];
    char frame_data[XMODEM_DATA_SIZE + XMODEM_CRC_SIZE + XMODEM_FRAME_ID_SIZE + 1];

    unsigned short crc_value;
    int complete = 0;
    int retry_num = 0;
    int pack_counter = 0;
    int read_number = 0;
    ack_id = 'C';
    int fd = 0;
	int bootfl = 263680;
	 int bootfl_t = bootfl;
	 int i = 0;

    //fd = FDI_fopen("firmware_file1", "rb");
    if (fd) 
    {
        sdk_uart_printf("debug> open file for read OK\n");
    }
    else 
    {
        sdk_uart_printf("debug> open file for read error\n");
        return -1;
    }    

    while(!complete)
	{
        switch(ack_id)
		{
            case XMODEM_CRC_CHR:	// 接收到字符'C'开始启动传输，并使用CRC校验
                sdk_uart_printf("begining to Send...\r\n");
            case XMODEM_ACK:        //0x06
                retry_num = 0;
				pack_counter++;

                //read_number = fread(packet_data, sizeof(char), XMODEM_DATA_SIZE, datafile);

                if(bootfl <= 0)
                {
                    ack_id = XMODEM_EOT;
                    complete = 1;
                    //FDI_fclose(fd);
                    UART3_SEND_DATA(&ack_id, 1);

                    sdk_uart_printf("Send file successful!!!\n");
                    //sleep(3);
                    break;
                }
               
                bootfl -= XMODEM_DATA_SIZE;
                if (bootfl >= 0)
                {
                    memset(packet_data, 0, XMODEM_DATA_SIZE);
                    //FDI_fread(packet_data, XMODEM_DATA_SIZE, 1, fd);
                  }   

                else
                {
                   
                    memset(packet_data, 0, bootfl_t);
                    //FDI_fread(packet_data, bootfl_t, 1, fd);
                    read_number = bootfl_t;
                    for(; read_number < XMODEM_DATA_SIZE; read_number++)
                    {
						packet_data[read_number] = 0x1A;
                    }
                }
                
                frame_data[0] = XMODEM_HEAD;  // 帧开始字符
				frame_data[1] = (char)pack_counter;  // 信息包序号
				frame_data[2] = (char)(255 - frame_data[1]);  // 信息包序号的补码
                
                for(i = 0; i < XMODEM_DATA_SIZE; i++)  // 128字节的数据段
				    frame_data[i+3] = packet_data[i];//把收到的字符和信息头一起打包

				crc_value = get_crc16(packet_data,  XMODEM_DATA_SIZE); // 16位crc校验
				frame_data[XMODEM_DATA_SIZE + 3] = (unsigned char)(crc_value >> 8);// 高八位数据
				frame_data[XMODEM_DATA_SIZE + 4] = (unsigned char)(crc_value);     //低八位数据
                lkfm3 = 0;
                UART3_SEND_DATA((char *)frame_data, XMODEM_DATA_SIZE + 5);

                while(1)
                {
                    if(lkfm3 == 1 )
                    {
                        lkfm3 = 0;
                        //sdk_uart_printf("aaa4\n");
                        //ack_id = XMODEM_ACK;
                        break;
                    }
                    OSATaskSleep(1);
                }
                break;


            case XMODEM_NAK:
                sdk_uart_printf("XMODEM_NAK\n");
                break;


            default:
                complete = 1;
                return -1;
        }
    }
}

static void _task2(void *ptr)
{
    sleep(10);
     Guilin_Ldo_4_set(1);
     UART_BaudRates baud;

     UART3_ENABLE();	// enable the uart3 without GPS
     baud = UART3_GET_BAUD();
	 sdk_uart_printf("%s: baud %d\n", __FUNCTION__, baud);
     sleep(3);
     UART3_SEND_DATA((char *)"$CFGPRT,1,0,115200,3,3\n", strlen("$CFGPRT,1,0,115200,3,3\n"));
     sleep(1);
	 UART3_SET_BAUD(115200);
     baud = UART3_GET_BAUD();
	 sdk_uart_printf("%s: -----  bau2 %d\n", __FUNCTION__, baud);

     SDK_GPS_ON_WITH_FIRMWARE();
     sleep(1);

    while (1) 
    {
        sdk_uart_printf("aaa9\n");
       UART3_SEND_DATA((char *)"$RESET,hf0,hff\n", strlen("$RESET,hf0,hff\n"));
       UART3_SEND_DATA((char *)"$RESET,hf0,hff\n", strlen("$RESET,hf0,hff\n"));

       while(1)
       {
           //sdk_uart_printf("aaaa\n");
           if(lkfm == 1 )
           {
               sdk_uart_printf("aaa0\n");
               break;
           }
           UART3_SEND_DATA((char *)"M!T", strlen("M!T"));
           OSATaskSleep(1);
       }

       while(1)
       {
           if(lkfm2 == 1 )
           {
               lkfm2 = 0;
               sdk_uart_printf("aaa1\n");
               break;
           }
           OSATaskSleep(10);
       }

       sdk_uart_printf("aaa1\n");

       xmodem_send1();

     UART3_SET_BAUD(460800);
     //UART3_SET_BAUD(230400);
	 //sdk_uart_printf("aaa6\n");
     baud = UART3_GET_BAUD();
	 sdk_uart_printf("%s: -----  bau2 %d\n", __FUNCTION__, baud);


     sleep(2);

       xmodem_send2();

sleep(2);
     UART3_SET_BAUD(115200);
     //UART3_SET_BAUD(230400);
	 //sdk_uart_printf("aaa6\n");
     baud = UART3_GET_BAUD();
	 sdk_uart_printf("%s: -----  bau2 %d\n", __FUNCTION__, baud);

     sleep(2);
     UART3_SEND_DATA((char *)"$PDTINFO\n", strlen("$PDTINFO\n"));
     sleep(2);
     Guilin_Ldo_4_set(1);
     sleep(2);
     SDK_GPS_ON_WITH_FIRMWARE();

     sleep(2);

     sleep(10);


     UART3_SEND_DATA((char *)"$CFGMSG,0,0,0\r\n", strlen("$CFGMSG,2,2,1\r\n"));
     //UART3_SEND_DATA((char *)"$CFGMSG,0,1,0\r\n", strlen("$CFGMSG,2,2,1\r\n"));
     UART3_SEND_DATA((char *)"$CFGMSG,0,2,0\r\n", strlen("$CFGMSG,2,2,1\r\n"));
     UART3_SEND_DATA((char *)"$CFGMSG,0,3,0\r\n", strlen("$CFGMSG,2,2,1\r\n"));
     UART3_SEND_DATA((char *)"$CFGMSG,0,4,0\r\n", strlen("$CFGMSG,2,2,1\r\n"));
     UART3_SEND_DATA((char *)"$CFGMSG,0,5,0\r\n", strlen("$CFGMSG,2,2,1\r\n"));
     UART3_SEND_DATA((char *)"$CFGMSG,0,6,0\r\n", strlen("$CFGMSG,2,2,1\r\n"));
     UART3_SEND_DATA((char *)"$CFGMSG,0,7,0\r\n", strlen("$CFGMSG,2,2,1\r\n"));
     UART3_SEND_DATA((char *)"$CFGSAVE,\r\n", strlen("$CFGSAVE,\r\n"));


     while(1)
     {
         sleep(10);

     }

       sleep(30000);
    }

}

extern OSMsgQRef uart3DataMsgQ;
static void _task(void *ptr)
{
	OSA_STATUS status;
	UINT32 flag_value;
	UINT32 flag_mask = TASK_TIMER_CHANGE_FLAG_BIT;
	uart3DataParam uart3_temp;	

	while(1) {
		status = OSAFlagWait(_flag_ref, flag_mask, OSA_FLAG_OR_CLEAR, &flag_value, OSA_SUSPEND);
		ASSERT(status == OS_SUCCESS);
		if (flag_value & TASK_TIMER_CHANGE_FLAG_BIT) 
		{
			static int count = 0;
			count++;
			sdk_uart_printf("_task: count: %d\n", count);

			if (count == 1) 
			{
				char temp[30];
				int fd = 0;
				OSA_STATUS status;

				sdk_uart_printf("%s[%d]: starting...\n", __FUNCTION__, __LINE__);
				status = OSAMsgQCreate(&uart3DataMsgQ, "uart3DataMsgQ", sizeof(uart3DataParam), 300, OS_FIFO);
				DIAG_ASSERT(status == OS_SUCCESS);

				ilkf = 0;   
				while (1) 
				{
					memset(&uart3_temp, 0, sizeof(uart3DataParam));
					status = OSAMsgQRecv(uart3DataMsgQ, (UINT8 *)&uart3_temp, sizeof(uart3DataParam), OSA_SUSPEND);//recv data from uart

					if (status == OS_SUCCESS) 
					{
						if (uart3_temp.UArgs) 
						{
							sdk_uart_printf("%s\r\n",  (char *)(uart3_temp.UArgs));

							if(strstr(uart3_temp.UArgs, "YC"))
							{
								lkfm = 1;
							}
							else if(strstr(uart3_temp.UArgs, "C"))
							{
								lkfm2 = 1;
							}
							else if(strstr(uart3_temp.UArgs, "begin to update"))
							{
								lkfm4 = 1;
							}
							else
							{
								unsigned int lkfack = uart3_temp.UArgs[0];
								ack_id = uart3_temp.UArgs[0];
								if(lkfack == XMODEM_ACK)
								{
									lkfm3 = 1;
								}
							}

							free(uart3_temp.UArgs);
						}
					}
					else
					{
						sdk_uart_printf("lkf 3\n");
					}

					ilkf++;
				}
			}

			if (count > 10) 
			{
				RTI_LOG("_task: stop timer");
				OSATimerStop(_timer_ref);
			}
		}
	}
}

static void _task3(void *ptr)
{
	OSA_STATUS status;
	UINT32 flag_value;
	msgGPSDataParam gps_msg = {0, NULL};
	char *gps_ptr = NULL;
	
	OSATaskSleep(200*5);
	sdk_uart_printf("GPS Start!\n");
    //SDK_GPS_ON();
	SDK_GPS_ON_WITH_FIRMWARE();

	while(1) {		    	
		status = OSAMsgQRecv(GpsDataMsgQ, (void *)&gps_msg, GPS_MSGQ_MSG_SIZE, OSA_SUSPEND);
		ASSERT(status == OS_SUCCESS);

		//sdk_uart_printf("_task gps_msg.len %d\n", gps_msg.len);


        sdk_uart_printf("lkf -- %s\r\n",  (char *)(gps_msg.UArgs));

// 		if (gps_msg.len){
// 			sdk_process_gpsdata((char *)gps_msg.UArgs, gps_msg.len);
// 		}

		if (gps_msg.UArgs)
			free(gps_msg.UArgs);
	}
}


char bootloader[13][1024] = {
};

unsigned char firmware[258][1024] = {
};



